<?php
/////////////////////////////////////////////////////////////////////////////
// 
//
// workflow_system 
//
// workflow_copyright
// 
/////////////////////////////////////////////////////////////////////////////

/**
 * FILE_NAME : pdo5.core.php   FILE_PATH : D:\webroot\_own\classes\core\pdo5.core.php
 * ....PHP5中PDO处理数据库类
 *
 * @copyright workflow_system 
 * @author workflow Develop Team 
 * @package 
 * @subpackage 
 * @version Tue Feb 26 17:08:31 CST 2008
 */

class DBEngine {
	/**
	 * 负责读数据库的数据库连接对象
	 *
	 * @var object
	 */
	var $_conn;
	/**
	 * 负责写数据库的数据库连接对象
	 *
	 * @var object
	 */
	var $_conn_write;
	/**
	 * 数据库表前缀
	 *
	 * @var string
	 */
	var $_dbprefix;

	/**
	 * 是否调试信息
	 *
	 * @var boolen
	 */
	var $ifdebug = false;

	/**
	 * 当前的数据库连接
	 *
	 * @var int
	 */
	var $conn;
	/**
	 * 其他数据库连接
	 *
	 * @var string
	 */
	var $_sys_conn_conn;
	var $_sys_conn_write;
	/**
	 * 使用UTF-8编码存取数据
	 *
	 * @var string
	 */
	var $utf_String = "
                 SET CHARACTER_SET_CLIENT = utf8,
                 CHARACTER_SET_CONNECTION = utf8,
                 CHARACTER_SET_DATABASE = utf8,
                 CHARACTER_SET_RESULTS = utf8,
                 CHARACTER_SET_SERVER = utf8,
                 COLLATION_CONNECTION = utf8_general_ci,
                 COLLATION_DATABASE = utf8_general_ci,
                 COLLATION_SERVER = utf8_general_ci,
                 AUTOCOMMIT=1
	       ";
	
	/**
	 * 连接数据库
	 *
	 */
	function _dbinitialize(){
		/**
		 * 连接到读数据库
		 */
		$conn = new PDO($GLOBALS['dbconfig']['database_type'] . ':host=' . $GLOBALS['dbconfig']['servername_read'] . ';dbname=' . $GLOBALS['dbconfig']['databasename_read'], $GLOBALS['dbconfig']['username_read'], $GLOBALS['dbconfig']['password_read']);
		/**
		 * 如果是读写分开的，写数据库连接
		 */
		if ($GLOBALS['dbconfig']['database_read_write'] == 1){
			$conn = new PDO($GLOBALS['dbconfig']['database_type'] . ':host=' . $GLOBALS['dbconfig']['servername_write'] . ';dbname=' . $GLOBALS['dbconfig']['databasename_write'], $GLOBALS['dbconfig']['username_write'], $GLOBALS['dbconfig']['password_write']);
		}else{
			$conn_write = $conn;
		}
		
		
		
		/**
		 * 是否是DEBUG模式
		 */
		/*
		if ($GLOBALS['dbconfig']['ifdebug'] == "true"){
			$conn->debug = true;
			$conn_write->debug = true;
		}
		else{
			$conn->debug = false;
			$conn_write->debug = false;
		}
		*/
		
		/**
		 * 设置表前缀
		 */
		$this->_dbprefix = $GLOBALS['dbconfig']['dbprefix'];
		$this->_conn = $conn;
		$this->_conn_write = $conn_write;

	}
	
	/**
	 * 将SQL语句里的表名称加上配置文件里的前缀
	 * 表名称必须用``括起来
	 * 返回值为加上了表前缀的SQL语句
	 * 例如，_settablename("select * from `member`")
	 * 得到的结果为，select * from `shopnc_member`
	 *
	 * @param string $strsql  SQL语句
	 * @return string
	 */
	function _settablename($strsql){
		if ($this->_dbprefix == ''){
			return $strsql;
		}
		$sqlarray = explode("`",$strsql);
		if (!is_array($sqlarray)){
			return $strsql;
		}else{
			for ($i=0;$i<count($sqlarray);$i++){
				if (($i+1)%2 == 0){
					if ($sqlarray[$i] == "")
					echo $strsql;
					if (!strstr($sqlarray[$i],$this->_dbprefix))
					$sqlarray[$i] = $this->_dbprefix . $sqlarray[$i];
				}
			}
			return implode("`",$sqlarray);
		}
	}

	
	/**
	 * 执行SQL语句
	 *
	 * @param string $sql
	 * @param string $link
	 * @return var
	 */
	function query($sql){
		$this->_conn->query($this->utf_String);
		$result = $this->_conn->query($sql);
		return $result;
	}
	
	/**
	 * 执行SQL语句
	 *
	 * @param string $sql
	 * @param string $link
	 * @return var
	 */
	function exce($sql){
		$this->_conn_write->exec($this->utf_String);
		$result = $this->_conn_write->exec($sql);
		return $result;
	}
	
	/**
	 * 根据SQL查询语句，得到一定范围内的记录数组
	 * 例如，得到前10条记录：SelectLimit("select * from `member` ",10,0)
	 * 得到的结果形式如$rs[行号][列名]
	 * 
	 * @param string $strsql  sql查询语句
	 * @param int $count  需要的记录数
	 * @param int $offset  从第几条开始
	 * @return var[] 二维数组
	 */
	function SelectLimit($strsql,$count,$offset){
		$strsql = $this->_settablename($strsql);
		$exe_sql = $strsql . " limit $offset,$count";
		return $this->GetArray($exe_sql);
	}
	
	/**
	 * 查询SQL语句，结果生成一个二维数组
	 * 形式如，$arr[行号][列名]
	 *
	 * @param string $strsql
	 * @return var[]
	 */
	function GetArray($strsql){
		$strsql = $this->_settablename($strsql);
		$result = $this->query($strsql);
		$array = $result->fetchAll();
		return $array;
	}
	
	/**
	 * 根据参数产生SQL插入语句
	 *
	 * @param object $tablename 要插入的表名称
	 * @param var[] $array 要插入的字段值，一维数组格式，$arr[列名] = 值
	 * @return string 返回的SQL语句
	 */
	function GetInsertSQL($tablename,$array){
		$sql = $this->_settablename("insert into `$tablename` ");
		foreach ($array as $k=>$v){
			$sub_sql .=  $k . ",";
		}

		if (substr($sub_sql,strlen($sub_sql)-1,1) == ","){
			$sub_sql = substr($sub_sql,0,strlen($sub_sql)-1);
		}
		$sub_sql = "(" . $sub_sql . ") values (";
		foreach ($array as $k=>$v){
			$sub_sql .= "'" . $v . "',";
		}
		if (substr($sub_sql,strlen($sub_sql)-1,1) == ","){
			$sub_sql = substr($sub_sql,0,strlen($sub_sql)-1);
		}
		$sub_sql = $sub_sql . ")";
		return $sql . $sub_sql;
	}

	/**
	 * 根据参数产生SQL更新语句
	 *
	 * @param object $tablename 要插入的表名称
	 * @param var[] $array 要更新的字段值，一维数组格式，$arr[列名] = 值
	 * @param object $wheresql 更新条件
	 * @return string 返回的SQL语句
	 */
	function GetUpdateSQL($tablename,$array,$wheresql="",$intfield=false){
		$sql = $this->_settablename("update `$tablename` set ");
		foreach ($array as $k=>$v){
			if($intfield === false){
				$sub_sql .= "$k='" . $v . "',";
			}else{
				$sub_sql .= "$k=" . $v . ",";
			}
		}
		if (substr($sub_sql,strlen($sub_sql)-1,1) == ","){
			$sub_sql = substr($sub_sql,0,strlen($sub_sql)-1);
		}
		return $sql . $sub_sql . " " . $wheresql;
	}
	
	/**
	 * 执行SQL语句
	 *
	 * @param string $strsql sql语句
	 * @return var
	 */
	function Execute($strsql){
		$strsql = $this->_settablename($strsql);
		if (strtolower(substr($strsql,0,6)) == "select"){
			//如果是查询那么用读数据库连接对象执行
			return $this->query($strsql);
		}else{
			//如果是需要对数据库进行更改的操作那么用写数据库连接对象执行
			return $this->exce($strsql);
		}
	}
	
	/**
	 * 得到一行信息放到数组中
	 *
	 * @param string $strsql SQL查询语句
	 * @return var[] 一维数组，形式如，$arr[列名]
	 */
	function GetRow($strsql){
		$strsql = $this->_settablename($strsql);
		$row = $this->SelectLimit($strsql,1,0);
		return $row[0];
	}
	
	/**
	 * 执行SQL指令，并且以阵列的方式回传第一笔记录的第一个栏位。资料集及其馀的记录将会被自动清除，如果发生错误，就回传 false 值。
	 *
	 * @param string $strsql
	 * @return var
	 */
	function GetOne($strsql){
		$strsql = $this->_settablename($strsql);
		$array = $this->SelectLimit($strsql,1,0);
		return $array[0][0];
	}
	
	/**
	 * 得到字段名称
	 *
	 * @param int $result
	 * @param int $f_index
	 * @return string
	 */
	function FetchField($result,$f_index){
		$column = $result->getColumnMeta($f_index);
		return $column['name'];
	}

	/**
	 * 得到结果集的字段数量
	 *
	 * @param int $result
	 * @return string[]
	 */
	function FieldCount($result){
		return $result->columnCount();
	}
	
	/**
	 * 连接到其他数据库，其他数据库没有读写分离，在使用后需要执行clearconnect。未clearconnect前执行的操作都是针对这个数据库的。
	 *
	 * @param string $databasename
	 */
	function connect($databasename){
		/**
		 * 读数据库连接
		 */	
		if ($conn = new PDO($GLOBALS['dbconfig']['database_type'] . ':host=' . $GLOBALS['dbconfig']['servername_read'] . ';dbname=' . $databasename, $GLOBALS['dbconfig']['username_read'], $GLOBALS['dbconfig']['password_read'])){
			$this->_sys_conn_conn = $this->_conn;
			$this->_sys_conn_conn_write = $this->_conn_write;
			$this->_conn = $connother;
			$this->_conn_write = $connother;
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 恢复数据库的连接
	 *
	 */
	function clearconnect(){
		$this->_conn = $this->_sys_conn_conn;
		$this->_conn_write = $this->_sys_conn_conn_write;
	}
}
?>